package com.djf.djfpgsql.wrapper.service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.djf.djfpgsql.entity.User;
import com.djf.djfpgsql.wrapper.mapper.UserWrapperMapper;
import com.baomidou.dynamic.datasource.annotation.DS;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 纯Wrapper方式的Service层实现
 * 展示MyBatis-Plus Wrapper在MySQL和PostgreSQL中的使用差异
 * 完全基于QueryWrapper和UpdateWrapper构建查询条件
 */
@Service
public class UserWrapperService extends ServiceImpl<UserWrapperMapper, User> {

    // ==================== 基础CRUD操作（完全兼容） ====================
    
    /**
     * 获取所有用户 - 通用方法
     * Wrapper方式：直接使用list()，无需区分数据库
     */
    public List<User> getAllUsers() {
        return list(); // MyBatis-Plus自动处理，MySQL和PostgreSQL完全兼容
    }
    
    /**
     * 根据ID获取用户 - 通用方法
     * Wrapper方式：使用QueryWrapper构建条件
     */
    public User getUserById(Long id) {
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.eq("id", id);
        return getOne(wrapper);
    }
    
    /**
     * 保存用户 - 通用方法
     * Wrapper方式：直接使用save()，无需区分数据库
     */
    public boolean saveUser(User user) {
        return save(user); // MyBatis-Plus自动处理主键生成策略
    }
    
    /**
     * 更新用户 - 通用方法
     * Wrapper方式：使用UpdateWrapper构建更新条件
     */
    public boolean updateUser(User user) {
        UpdateWrapper<User> wrapper = new UpdateWrapper<>();
        wrapper.eq("id", user.getId());
        return update(user, wrapper);
    }
    
    /**
     * 删除用户 - 通用方法
     * Wrapper方式：使用QueryWrapper构建删除条件
     */
    public boolean deleteUser(Long id) {
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.eq("id", id);
        return remove(wrapper);
    }

    // ==================== 条件查询（完全兼容） ====================
    
    /**
     * 根据年龄范围查询用户 - 通用方法
     * Wrapper方式：使用ge()和le()方法
     */
    public List<User> getUsersByAgeRange(Integer minAge, Integer maxAge) {
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        if (minAge != null) {
            wrapper.ge("age", minAge);
        }
        if (maxAge != null) {
            wrapper.le("age", maxAge);
        }
        wrapper.orderByAsc("age");
        return list(wrapper);
    }
    
    /**
     * 根据余额范围查询用户 - 通用方法
     * Wrapper方式：使用between()方法
     */
    public List<User> getUsersByBalanceRange(Double minBalance, Double maxBalance) {
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.between("balance", minBalance, maxBalance);
        wrapper.orderByDesc("balance");
        return list(wrapper);
    }
    
    /**
     * 根据活跃状态查询用户 - 通用方法
     * Wrapper方式：MyBatis-Plus自动处理布尔值转换
     */
    public List<User> getUsersByActiveStatus(Boolean isActive) {
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.eq("is_active", isActive); // MP自动转换：MySQL->1/0, PostgreSQL->true/false
        return list(wrapper);
    }
    
    /**
     * 根据邮箱域名查询用户 - 通用方法
     * Wrapper方式：使用like()方法
     */
    public List<User> getUsersByEmailDomain(String domain) {
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.like("email", "@" + domain);
        return list(wrapper);
    }

    // ==================== 数据库特定的字符串查询 ====================
    
    /**
     * 字符串模糊搜索 - MySQL版本
     * Wrapper方式：使用apply()方法编写MySQL特定语法
     */
    public List<User> searchUsersByNameMySQL(String name) {
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        // MySQL: LIKE + CONCAT，区分大小写
        wrapper.apply("name LIKE CONCAT('%', {0}, '%')", name);
        return list(wrapper);
    }
    
    /**
     * 字符串模糊搜索 - PostgreSQL版本
     * Wrapper方式：使用apply()方法编写PostgreSQL特定语法
     */
    @DS("pgsql")
    public List<User> searchUsersByNamePGSQL(String name) {
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        // PostgreSQL: ILIKE + ||，不区分大小写
        wrapper.apply("name ILIKE '%' || {0} || '%'", name);
        return list(wrapper);
    }
    
    /**
     * 多字段模糊搜索 - MySQL版本
     * Wrapper方式：组合多个apply()条件
     */
    public List<User> searchUsersMultiFieldMySQL(String keyword) {
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.and(w -> w
            .apply("name LIKE CONCAT('%', {0}, '%')", keyword)
            .or()
            .apply("email LIKE CONCAT('%', {0}, '%')", keyword)
        );
        return list(wrapper);
    }
    
    /**
     * 多字段模糊搜索 - PostgreSQL版本
     * Wrapper方式：组合多个apply()条件
     */
    @DS("pgsql")
    public List<User> searchUsersMultiFieldPGSQL(String keyword) {
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.and(w -> w
            .apply("name ILIKE '%' || {0} || '%'", keyword)
            .or()
            .apply("email ILIKE '%' || {0} || '%'", keyword)
        );
        return list(wrapper);
    }

    // ==================== 数据库特定的日期查询 ====================
    
    /**
     * 日期范围查询 - MySQL版本
     * Wrapper方式：使用apply()方法编写MySQL日期函数
     */
    public List<User> getRecentUsersMySQL(int days) {
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        // MySQL: DATE_SUB(NOW(), INTERVAL ? DAY)
        wrapper.apply("created_at >= DATE_SUB(NOW(), INTERVAL {0} DAY)", days);
        wrapper.orderByDesc("created_at");
        return list(wrapper);
    }
    
    /**
     * 日期范围查询 - PostgreSQL版本
     * Wrapper方式：使用apply()方法编写PostgreSQL日期函数
     */
    @DS("pgsql")
    public List<User> getRecentUsersPGSQL(int days) {
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        // PostgreSQL: NOW() - INTERVAL '? days'
        wrapper.apply("created_at >= NOW() - INTERVAL '{0} days'", days);
        wrapper.orderByDesc("created_at");
        return list(wrapper);
    }
    
    /**
     * 通用日期范围查询 - 推荐方式
     * Wrapper方式：使用Java LocalDateTime，避免数据库特定函数
     */
    public List<User> getRecentUsersUniversal(int days) {
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        LocalDateTime startDate = LocalDateTime.now().minusDays(days);
        wrapper.ge("created_at", startDate); // 使用ge()方法，MP自动处理
        wrapper.orderByDesc("created_at");
        return list(wrapper);
    }
    
    /**
     * 按月份统计用户 - MySQL版本
     * Wrapper方式：使用apply()和groupBy()组合
     */
    public List<Map<String, Object>> getUserCountByMonthMySQL() {
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.select("DATE_FORMAT(created_at, '%Y-%m') as month", "COUNT(*) as user_count");
        wrapper.groupBy("DATE_FORMAT(created_at, '%Y-%m')");
        wrapper.orderByAsc("month");
        return listMaps(wrapper);
    }
    
    /**
     * 按月份统计用户 - PostgreSQL版本
     * Wrapper方式：使用apply()和groupBy()组合
     */
    @DS("pgsql")
    public List<Map<String, Object>> getUserCountByMonthPGSQL() {
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.select("TO_CHAR(created_at, 'YYYY-MM') as month", "COUNT(*) as user_count");
        wrapper.groupBy("TO_CHAR(created_at, 'YYYY-MM')");
        wrapper.orderByAsc("month");
        return listMaps(wrapper);
    }

    // ==================== 数据库特定的JSON查询 ====================
    
    /**
     * JSON字段查询 - MySQL版本
     * Wrapper方式：使用apply()方法编写MySQL JSON函数
     */
    public List<User> getUsersByCityMySQL(String city) {
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        // MySQL: JSON_EXTRACT(profile, '$.city') = ?
        wrapper.apply("JSON_EXTRACT(profile, '$.city') = {0}", city);
        return list(wrapper);
    }
    
    /**
     * JSON字段查询 - PostgreSQL版本
     * Wrapper方式：使用apply()方法编写PostgreSQL JSON操作符
     */
    @DS("pgsql")
    public List<User> getUsersByCityPGSQL(String city) {
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        // PostgreSQL: profile->>'city' = ?
        wrapper.apply("profile->>'city' = {0}", city);
        return list(wrapper);
    }
    
    /**
     * 复杂JSON查询 - MySQL版本
     * Wrapper方式：组合多个JSON条件
     */
    public List<User> getUsersByProfileMySQL(String city, Integer minAge) {
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        if (city != null) {
            wrapper.apply("JSON_EXTRACT(profile, '$.city') = {0}", city);
        }
        if (minAge != null) {
            wrapper.apply("JSON_EXTRACT(profile, '$.age') >= {0}", minAge);
        }
        return list(wrapper);
    }
    
    /**
     * 复杂JSON查询 - PostgreSQL版本
     * Wrapper方式：组合多个JSON条件
     */
    @DS("pgsql")
    public List<User> getUsersByProfilePGSQL(String city, Integer minAge) {
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        if (city != null) {
            wrapper.apply("profile->>'city' = {0}", city);
        }
        if (minAge != null) {
            wrapper.apply("(profile->>'age')::int >= {0}", minAge);
        }
        return list(wrapper);
    }

    // ==================== 统计和聚合查询 ====================
    
    /**
     * 用户统计 - MySQL版本
     * Wrapper方式：使用count()方法和条件组合
     */
    public Map<String, Object> getUserStatisticsMySQL() {
        Map<String, Object> result = new HashMap<>();
        
        // 总用户数
        result.put("total_users", count());
        
        // 活跃用户数 - MySQL中布尔值为1
        QueryWrapper<User> activeWrapper = new QueryWrapper<>();
        activeWrapper.eq("is_active", 1);
        result.put("active_users", count(activeWrapper));
        
        // 平均年龄
        QueryWrapper<User> avgAgeWrapper = new QueryWrapper<>();
        avgAgeWrapper.select("AVG(age) as avg_age");
        Map<String, Object> avgAge = getMap(avgAgeWrapper);
        result.put("avg_age", avgAge.get("avg_age"));
        
        // 平均余额
        QueryWrapper<User> avgBalanceWrapper = new QueryWrapper<>();
        avgBalanceWrapper.select("AVG(balance) as avg_balance");
        Map<String, Object> avgBalance = getMap(avgBalanceWrapper);
        result.put("avg_balance", avgBalance.get("avg_balance"));
        
        result.put("database_type", "MySQL");
        result.put("boolean_representation", "1/0");
        
        return result;
    }
    
    /**
     * 用户统计 - PostgreSQL版本
     * Wrapper方式：使用count()方法和条件组合
     */
    @DS("pgsql")
    public Map<String, Object> getUserStatisticsPGSQL() {
        Map<String, Object> result = new HashMap<>();
        
        // 总用户数
        result.put("total_users", count());
        
        // 活跃用户数 - PostgreSQL中布尔值为true
        QueryWrapper<User> activeWrapper = new QueryWrapper<>();
        activeWrapper.eq("is_active", true);
        result.put("active_users", count(activeWrapper));
        
        // 平均年龄
        QueryWrapper<User> avgAgeWrapper = new QueryWrapper<>();
        avgAgeWrapper.select("AVG(age) as avg_age");
        Map<String, Object> avgAge = getMap(avgAgeWrapper);
        result.put("avg_age", avgAge.get("avg_age"));
        
        // 平均余额
        QueryWrapper<User> avgBalanceWrapper = new QueryWrapper<>();
        avgBalanceWrapper.select("AVG(balance) as avg_balance");
        Map<String, Object> avgBalance = getMap(avgBalanceWrapper);
        result.put("avg_balance", avgBalance.get("avg_balance"));
        
        result.put("database_type", "PostgreSQL");
        result.put("boolean_representation", "true/false");
        
        return result;
    }

    // ==================== 更新操作 ====================
    
    /**
     * 批量更新用户状态 - 通用方法
     * Wrapper方式：使用UpdateWrapper构建更新条件
     */
    public boolean batchUpdateUserStatus(List<Long> userIds, Boolean isActive) {
        UpdateWrapper<User> wrapper = new UpdateWrapper<>();
        wrapper.in("id", userIds);
        wrapper.set("is_active", isActive); // MP自动处理布尔值转换
        wrapper.set("updated_at", LocalDateTime.now());
        return update(wrapper);
    }
    
    /**
     * 时间戳更新 - MySQL版本
     * Wrapper方式：使用UpdateWrapper + setSql()方法
     */
    public boolean updateLastLoginMySQL(Long userId) {
        UpdateWrapper<User> wrapper = new UpdateWrapper<>();
        wrapper.eq("id", userId);
        wrapper.setSql("last_login = NOW()"); // MySQL特有语法
        return update(wrapper);
    }
    
    /**
     * 时间戳更新 - PostgreSQL版本
     * Wrapper方式：使用UpdateWrapper + setSql()方法
     */
    @DS("pgsql")
    public boolean updateLastLoginPGSQL(Long userId) {
        UpdateWrapper<User> wrapper = new UpdateWrapper<>();
        wrapper.eq("id", userId);
        wrapper.setSql("last_login = CURRENT_TIMESTAMP"); // PostgreSQL特有语法
        return update(wrapper);
    }
    
    /**
     * 通用时间戳更新 - 推荐方式
     * Wrapper方式：使用Java LocalDateTime
     */
    public boolean updateLastLoginUniversal(Long userId) {
        UpdateWrapper<User> wrapper = new UpdateWrapper<>();
        wrapper.eq("id", userId);
        wrapper.set("last_login", LocalDateTime.now()); // MP自动处理时间格式
        return update(wrapper);
    }
    
    /**
     * 条件更新用户余额 - 通用方法
     * Wrapper方式：使用UpdateWrapper构建复杂更新条件
     */
    public boolean updateUserBalance(Long userId, Double amount, String operation) {
        UpdateWrapper<User> wrapper = new UpdateWrapper<>();
        wrapper.eq("id", userId);
        
        if ("add".equals(operation)) {
            wrapper.setSql("balance = balance + " + amount);
        } else if ("subtract".equals(operation)) {
            wrapper.setSql("balance = balance - " + amount);
        } else {
            wrapper.set("balance", amount);
        }
        
        wrapper.set("updated_at", LocalDateTime.now());
        return update(wrapper);
    }

    // ==================== 排序和分页 ====================
    
    /**
     * 获取排行榜用户 - 通用方法
     * Wrapper方式：使用orderBy()和last()方法
     */
    public List<User> getTopUsersByBalance(int limit) {
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.orderByDesc("balance");
        wrapper.last("LIMIT " + limit); // MySQL和PostgreSQL语法相同
        return list(wrapper);
    }
    
    /**
     * 分页查询用户 - 通用方法
     * Wrapper方式：结合分页插件使用
     */
    public List<User> getUsersWithPagination(int page, int size, String sortField, String sortOrder) {
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        
        if ("asc".equalsIgnoreCase(sortOrder)) {
            wrapper.orderByAsc(sortField);
        } else {
            wrapper.orderByDesc(sortField);
        }
        
        // 使用LIMIT和OFFSET（MySQL和PostgreSQL通用）
        int offset = (page - 1) * size;
        wrapper.last("LIMIT " + size + " OFFSET " + offset);
        
        return list(wrapper);
    }

    // ==================== 复杂组合查询 ====================
    
    /**
     * 复杂条件查询示例 - 通用方法
     * Wrapper方式：展示条件构造器的强大功能
     */
    public List<User> getComplexQueryUsers(
            String namePattern, 
            Integer minAge, 
            Integer maxAge,
            Double minBalance,
            Boolean isActive,
            String emailDomain,
            LocalDateTime startDate,
            LocalDateTime endDate) {
        
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        
        // 姓名模糊查询
        if (namePattern != null && !namePattern.isEmpty()) {
            wrapper.like("name", namePattern);
        }
        
        // 年龄范围
        if (minAge != null) {
            wrapper.ge("age", minAge);
        }
        if (maxAge != null) {
            wrapper.le("age", maxAge);
        }
        
        // 余额条件
        if (minBalance != null) {
            wrapper.ge("balance", minBalance);
        }
        
        // 活跃状态
        if (isActive != null) {
            wrapper.eq("is_active", isActive);
        }
        
        // 邮箱域名
        if (emailDomain != null && !emailDomain.isEmpty()) {
            wrapper.like("email", "@" + emailDomain);
        }
        
        // 创建时间范围
        if (startDate != null) {
            wrapper.ge("created_at", startDate);
        }
        if (endDate != null) {
            wrapper.le("created_at", endDate);
        }
        
        // 排序
        wrapper.orderByDesc("created_at", "balance");
        
        return list(wrapper);
    }
    
    /**
     * 动态查询构建器 - 通用方法
     * Wrapper方式：根据参数动态构建查询条件
     */
    public List<User> getDynamicQueryUsers(Map<String, Object> params) {
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        
        params.forEach((key, value) -> {
            if (value != null) {
                switch (key) {
                    case "name":
                        wrapper.like("name", value.toString());
                        break;
                    case "email":
                        wrapper.like("email", value.toString());
                        break;
                    case "minAge":
                        wrapper.ge("age", value);
                        break;
                    case "maxAge":
                        wrapper.le("age", value);
                        break;
                    case "isActive":
                        wrapper.eq("is_active", value);
                        break;
                    case "minBalance":
                        wrapper.ge("balance", value);
                        break;
                    default:
                        // 忽略未知参数
                        break;
                }
            }
        });
        
        return list(wrapper);
    }
}

/*
 * 纯Wrapper方式的优势总结：
 * 
 * 1. 类型安全：
 *    - 编译时检查，减少SQL错误
 *    - IDE智能提示，提高开发效率
 * 
 * 2. 代码复用：
 *    - 通用的条件构造逻辑
 *    - 减少重复的SQL代码
 * 
 * 3. 动态查询：
 *    - 根据条件动态构建SQL
 *    - 避免大量的if-else判断
 * 
 * 4. 自动处理：
 *    - 参数绑定和类型转换
 *    - 防SQL注入
 * 
 * 5. 可读性强：
 *    - 链式调用，逻辑清晰
 *    - 方法名语义化
 * 
 * 6. 数据库兼容性：
 *    - 基础操作完全兼容
 *    - 特殊功能使用apply()方法
 * 
 * 7. 维护性好：
 *    - 统一的编码风格
 *    - 易于重构和扩展
 */